package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.util.NumberUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.after.sale.entity.QReplaceGoodsDetailAssociatedDO;
import com.ssy.lingxi.after.sale.entity.QReplaceGoodsDetailDO;
import com.ssy.lingxi.after.sale.entity.ReplaceGoodsDO;
import com.ssy.lingxi.after.sale.entity.ReplaceGoodsDetailDO;
import com.ssy.lingxi.after.sale.model.constant.CommonBooleanEnum;
import com.ssy.lingxi.after.sale.model.constant.ReplaceGoodsInnerStatusEnum;
import com.ssy.lingxi.after.sale.model.constant.ReplaceGoodsOuterStatusEnum;
import com.ssy.lingxi.after.sale.model.vo.request.ReplaceGoodsDetailPageVO;
import com.ssy.lingxi.after.sale.model.vo.request.ReplaceGoodsDetailSetStatusVO;
import com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailQueryVO;
import com.ssy.lingxi.after.sale.repository.ReplaceGoodsDetailRepository;
import com.ssy.lingxi.after.sale.repository.ReplaceGoodsRepository;
import com.ssy.lingxi.after.sale.service.IReplaceGoodsDetailService;
import com.ssy.lingxi.after.sale.utils.ParamVerifyUtils;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 售后换货商品接口服务实现
 * @author 伍将
 * @date 2020/9/11
 * @version 2.0.0
 */
@Service
public class ReplaceGoodsDetailServiceImpl implements IReplaceGoodsDetailService {

    @Resource
    private ReplaceGoodsDetailRepository repository;

    @Resource
    private ReplaceGoodsRepository replaceGoodsRepository;
    @Resource
    private JPAQueryFactory jpaQueryFactory;

    /**
     * 分页查询换货商品
     * @author 伍将
     * @date 2020/9/11
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceedGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsDetailQueryVO>> pageList(UserLoginCacheDTO loginUser,ReplaceGoodsDetailPageVO pageVO) {
        ReplaceGoodsDO repairGoodsDO = replaceGoodsRepository.findById(pageVO.getReplaceId()).orElse(null);
        if(repairGoodsDO==null){
            return Wrapper.success(new PageData<>(0L, null));
        }
        PageData<ReplaceGoodsDetailQueryVO> pageData;
        if(ParamVerifyUtils.isContractOrderType(repairGoodsDO.getOrderType())){//合同订单类型（询价、竞价、招标合同）
            pageData=pageMaterielList(loginUser,pageVO);
        }else{
            pageData=pageProductList(loginUser,pageVO);
        }
        return Wrapper.success(pageData);
    }

    private PageData<ReplaceGoodsDetailQueryVO> pageProductList(UserLoginCacheDTO loginUser,ReplaceGoodsDetailPageVO pageVO){
        // step 1: 组装查询条件
        Specification<ReplaceGoodsDetailDO> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("replaceId").as(Long.class), pageVO.getReplaceId()));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDetailDO> result = repository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReplaceGoodsDetailQueryVO> resultList = result.getContent().stream().map(r -> {
            ReplaceGoodsDetailQueryVO queryVO = new ReplaceGoodsDetailQueryVO();
            queryVO.setDetailId(r.getId());
            queryVO.setOrderNo(r.getOrderNo());
            queryVO.setOrderRecordId(r.getOrderRecordId());
            queryVO.setProductId(r.getProductId());
            queryVO.setProductName(r.getProductName());
            queryVO.setCategory(r.getCategory());
            queryVO.setBrand(r.getBrand());
            queryVO.setUnit(r.getUnit());
            queryVO.setPurchaseCount(r.getPurchaseCount());
            queryVO.setPurchasePrice(r.getPurchasePrice());
            queryVO.setPurchaseAmount(r.getPurchaseAmount());
            queryVO.setReplaceCount(r.getReplaceCount());
            queryVO.setReplaceReason(r.getReplaceReason());
            queryVO.setNeedReplaceName(CommonBooleanEnum.getMessage(r.getIsNeedReturn()));
            queryVO.setIsNeedReturn(r.getIsNeedReturn());
            queryVO.setIsHasTax(r.getIsHasTax());
            queryVO.setTaxRate(r.getTaxRate());
            queryVO.setContractId(r.getContractId());
            queryVO.setContractNo(r.getContractNo());
            queryVO.setDeliveryCount(r.getReturnDeliveryCount());
            queryVO.setNoDeliveryCount(NumberUtil.sub(r.getReplaceCount(),r.getReturnDeliveryCount()));
            queryVO.setReceiveCount(r.getReturnReceiveCount());
            queryVO.setSubCount(NumberUtil.sub(r.getReturnDeliveryCount(),r.getReturnReceiveCount()));
            return queryVO;
        }).collect(Collectors.toList());
        return new PageData<>(result.getTotalElements(), resultList);
    }

    private PageData<ReplaceGoodsDetailQueryVO> pageMaterielList(UserLoginCacheDTO loginUser,ReplaceGoodsDetailPageVO pageVO){
        // 查询表实体
        QReplaceGoodsDetailDO replaceGoodsDetailDO = QReplaceGoodsDetailDO.replaceGoodsDetailDO;
        QReplaceGoodsDetailAssociatedDO replaceGoodsDetailMaterielDO=QReplaceGoodsDetailAssociatedDO.replaceGoodsDetailAssociatedDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(replaceGoodsDetailDO.replaceId.eq(pageVO.getReplaceId()));
        // 关联查询
        JPAQuery<ReplaceGoodsDetailQueryVO> query = jpaQueryFactory
                .select(Projections.bean(ReplaceGoodsDetailQueryVO.class,
                        replaceGoodsDetailDO.id.as("detailId"),
                        replaceGoodsDetailDO.orderRecordId,
                        replaceGoodsDetailDO.orderNo,
                        replaceGoodsDetailDO.productId,
                        replaceGoodsDetailDO.productName,
                        replaceGoodsDetailDO.type,
                        replaceGoodsDetailDO.category,
                        replaceGoodsDetailDO.brand,
                        replaceGoodsDetailDO.unit,
                        replaceGoodsDetailDO.purchaseCount,
                        replaceGoodsDetailDO.purchasePrice,
                        replaceGoodsDetailDO.purchaseAmount,
                        replaceGoodsDetailDO.replaceCount,
                        replaceGoodsDetailDO.replaceReason,
                        replaceGoodsDetailDO.isNeedReturn,
                        replaceGoodsDetailDO.isHasTax,
                        replaceGoodsDetailDO.taxRate,
                        replaceGoodsDetailDO.contractId,
                        replaceGoodsDetailDO.contractNo,
                        replaceGoodsDetailMaterielDO.productId.as("associatedProductId"),
                        replaceGoodsDetailMaterielDO.productName.as("associatedProductName"),
                        replaceGoodsDetailMaterielDO.brand.as("associatedBrand"),
                        replaceGoodsDetailMaterielDO.category.as("associatedCategory"),
                        replaceGoodsDetailMaterielDO.unit.as("associatedUnit"),
                        replaceGoodsDetailMaterielDO.type.as("associatedType"))
                )
                .from(replaceGoodsDetailMaterielDO)
                .leftJoin(replaceGoodsDetailDO)
                .on(replaceGoodsDetailMaterielDO.replaceDetailId.eq(replaceGoodsDetailDO.id))
                .where(predicates);

        long totalCount = query.fetchCount();
        List<ReplaceGoodsDetailQueryVO> responses = query.orderBy(replaceGoodsDetailMaterielDO.id.desc())
                .offset(pageVO.getCurrentOffset())
                .limit(pageVO.getPageSize())
                .fetch();
        //数值对应名称处理
        responses.forEach(o -> o.setNeedReplaceName(CommonBooleanEnum.getMessage(o.getIsNeedReturn())));
        return new PageData<>(totalCount, responses);
    }

    /**
     * 设置需要退货
     * @author 伍将
     * @date 2020/9/16
     * @param user :
     * @param setStatusVO :
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> setNeedReturnGoods(UserLoginCacheDTO user, ReplaceGoodsDetailSetStatusVO setStatusVO) {
        if (setStatusVO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_SET_RETURN_PARAM_EMPTY);
        }
        if (!setStatusVO.getIsNeed().equals(CommonBooleanEnum.NO.getCode())
                && !setStatusVO.getIsNeed().equals(CommonBooleanEnum.YES.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_SET_RETURN_PARAM_ERROR);
        }
        ReplaceGoodsDO replaceDO = replaceGoodsRepository.findById(setStatusVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_UN_ALLOW_SET_RETURN_GOODS);
        }
        ReplaceGoodsDetailDO detailDO = repository.findById(setStatusVO.getReplaceGoodsId()).orElse(null);
        if (detailDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 如果换货id与换货商品所属换货id不匹配，则说明参数错误
        if (!replaceDO.getId().equals(detailDO.getReplaceId())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_SET_RETURN_PARAM_ERROR);
        }
        detailDO.setIsNeedReturn(setStatusVO.getIsNeed());
        repository.saveAndFlush(detailDO);

        return Wrapper.success();
    }
}
